package org.zoomdev.android.reactnative.nfc;

import android.app.Activity;
import android.content.Intent;
import android.nfc.tech.IsoDep;
import android.nfc.tech.MifareClassic;

import com.facebook.react.bridge.ActivityEventListener;
import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.zoomdev.android.hex.HexUtil;

import org.zoomdev.android.nfc.NfcListener;
import org.zoomdev.android.nfc.NfcModel;
import org.zoomdev.android.nfc.adapters.IsoDepTagAdapter;
import org.zoomdev.android.nfc.adapters.MifareOneTagAdapter;
import org.zoomdev.android.nfc.adapters.NfcTagAdapter;

import java.io.IOException;

public class NfcModule extends ReactContextBaseJavaModule
        implements LifecycleEventListener, NfcListener, ActivityEventListener {


    private NfcModel model;


    public NfcModule(ReactApplicationContext reactContext) {
        super(reactContext);

    }


    @Override
    public synchronized void initialize() {
        super.initialize();
        getReactApplicationContext().addLifecycleEventListener(this);
        getReactApplicationContext().addActivityEventListener(this);
        getModel();
    }

    @Override
    public synchronized void onCatalystInstanceDestroy() {
        super.onCatalystInstanceDestroy();
        getReactApplicationContext().removeLifecycleEventListener(this);
        getReactApplicationContext().removeActivityEventListener(this);
        getModel().destroy();
    }



    @Override
    public void onNfcEvent(NfcTagAdapter nfcTagAdapter) {
        getReactApplicationContext()
                .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit("onNFC", nfcTagAdapter.getTech());

    }


    @ReactMethod
    public synchronized void close(Promise promise) {
        getModel().close();
        promise.resolve(true);
    }


    @ReactMethod
    public synchronized void connect(Promise promise) {
        NfcTagAdapter adapter = getModel().getAdapter();
        if (adapter != null) {
            try {
                adapter.connect();
                promise.resolve(true);
                return;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        promise.reject("io", "连接失败");

    }

    @ReactMethod
    public synchronized void apdu(String cmd, Promise promise) {
        IsoDepTagAdapter adapter = getModel().getAdapter();
        IsoDep isoDep = adapter.getTag();
        if (adapter != null && isoDep != null) {
            try {
                byte[] response = isoDep.transceive(HexUtil.decodeHex(cmd));
                promise.resolve(HexUtil.encodeHexStr(response));
                return;
            } catch (IOException e) {

            }
        }
        promise.reject("io", "调用失败");
    }

    @ReactMethod
    public synchronized void mifareOneWriteBlock(
            int block, String data, Promise promise
    ) {
        MifareOneTagAdapter adapter = model.getAdapter();
        MifareClassic mifareClassic = adapter.getTag();
        if (adapter != null && mifareClassic != null) {
            try {
                mifareClassic.writeBlock(block, HexUtil.decodeHex(data));
                promise.resolve(true);
                return;
            } catch (IOException e) {

            }
        }
        promise.reject("io", "调用失败");
    }

    @ReactMethod
    public synchronized void mifareOneReadBlock(
            int block, Promise promise
    ) {
        MifareOneTagAdapter adapter = getModel().getAdapter();
        MifareClassic mifareClassic = adapter.getTag();
        if (adapter != null && mifareClassic != null) {
            try {
                byte[] bytes = mifareClassic.readBlock(block);
                promise.resolve(HexUtil.encodeHex(bytes));
                return;
            } catch (IOException e) {

            }
        }
        promise.reject("io", "调用失败");
    }


    @ReactMethod
    public synchronized void mifareOneTransfer(
            int block, Promise promise
    ) {
        MifareOneTagAdapter adapter = getModel().getAdapter();
        MifareClassic mifareClassic = adapter.getTag();
        if (adapter != null && mifareClassic != null) {
            try {
                mifareClassic.transfer(block);
                promise.resolve(true);
                return;
            } catch (IOException e) {

            }
        }
        promise.reject("io", "调用失败");
    }

    @ReactMethod
    public synchronized void mifareOneRestore(
            int block, Promise promise
    ) {
        MifareOneTagAdapter adapter = getModel().getAdapter();
        MifareClassic mifareClassic = adapter.getTag();
        if (adapter != null && mifareClassic != null) {
            try {
                mifareClassic.restore(block);
                promise.resolve(true);
                return;
            } catch (IOException e) {

            }
        }
        promise.reject("io", "调用失败");
    }

    @ReactMethod
    public synchronized void mifareOneIncrement(
            int block, int value, Promise promise
    ) {
        MifareOneTagAdapter adapter = getModel().getAdapter();
        MifareClassic mifareClassic = adapter.getTag();
        if (adapter != null && mifareClassic != null) {
            try {
                mifareClassic.increment(block, value);
                promise.resolve(true);
                return;
            } catch (IOException e) {

            }
        }
        promise.reject("io", "调用失败");
    }

    @ReactMethod
    public synchronized void mifareOneDecrement(
            int block, int value, Promise promise
    ) {
        MifareOneTagAdapter adapter = getModel().getAdapter();
        MifareClassic mifareClassic = adapter.getTag();
        if (adapter != null && mifareClassic != null) {
            try {
                mifareClassic.decrement(block, value);
                promise.resolve(true);
                return;
            } catch (IOException e) {

            }
        }
        promise.reject("io", "调用失败");
    }


    @ReactMethod
    public synchronized void mifareOneAuthenticate(
            int block, int type, String key, Promise promise
    ) {
        MifareOneTagAdapter adapter = getModel().getAdapter();
        MifareClassic mifareClassic = adapter.getTag();
        if (adapter != null && mifareClassic != null) {
            try {
                if (type == 0) {
                    mifareClassic.authenticateSectorWithKeyA(block, HexUtil.decodeHex(key));
                } else {
                    mifareClassic.authenticateSectorWithKeyB(block, HexUtil.decodeHex(key));
                }
                promise.resolve(true);
                return;
            } catch (IOException e) {

            }
        }
        promise.reject("io", "调用失败");
    }


    @Override
    public String getName() {
        return "NfcModule";
    }

    private boolean resumed = false;

    @Override
    public synchronized void onHostResume() {
        resumed = true;
        if (model != null)
            model.onResume(getCurrentActivity());
    }

    @Override
    public synchronized void onHostPause() {
        resumed = false;
        if (model != null)
            model.onPause(getCurrentActivity());
    }

    @Override
    public synchronized void onHostDestroy() {

    }


    @Override
    public void onActivityResult(Activity activity, int i, int i1, Intent intent) {

    }


    public NfcModel getModel(){
        NfcModel model = this.model;
        if (model == null) {
            model = new NfcModel(getCurrentActivity(), new IsoDepTagAdapter.Factory(), new MifareOneTagAdapter.Factory());
            model.setAdapterListener(this);
            this.model = model;
        }
        return model;
    }

    @Override
    public synchronized void onNewIntent(Intent intent) {
        getModel().onNewIntent(intent);
    }
}
